﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Windows.Forms;
using Windstamp.Utility.BookDownload.Common;
using Windstamp.Utility.BookDownload.Core;

namespace Windstamp.Utility.BookDownload.PWADSWinForm {
    public partial class formPWADS : Form {
        BindingSource bData = new BindingSource();
        Dictionary<DownloadPageStatus, string> downloadPageStatusNames;
        DownloadEntrance currentEntrance;
        string mainFolder;

        public formPWADS() {
            InitializeComponent();

            downloadPageStatusNames = new Dictionary<DownloadPageStatus, string>() {
                {DownloadPageStatus.Ready, "准备"},
                {DownloadPageStatus.Downloading, "下载中..."},
                {DownloadPageStatus.Finished, "完成"},
                {DownloadPageStatus.Stoped, "被停止"},
                {DownloadPageStatus.Error, "错误"}
            };

            mainFolder = UniversalHelper.GetCurrentPaths(UniversalHelper.CurrentPathType.System_AppDomain_CurrentDomain_SetupInformation_ApplicationBase);
        }

        private void formPWADS_Load(object sender, EventArgs e) {
            InitVer();
            InitPromptHelper();
            InitZoomItems();

            statusStrip1.Items.Add(new ToolStripStatusLabel("状态："));
            statusStrip1.Items.Add(new ToolStripStatusLabel("就绪"));

            InitGridMainPage();

            List<DownloadPageInfo> data = new List<DownloadPageInfo>();
            bData.DataSource = data;
            gridMainPage.DataSource = bData;

            InitData();

            gridMainPage.CellClick += OnGridMainPageRemoveCellClick;

            ClipboardMonitor();

            //this.Invoke(new Action(() => {
            //    var webForm = new AntispiderShowVerifyForm() { AntispiderShowVerifyUrl = "http://www.baidu.com" };
            //    webForm.Text = "百度";
            //    webForm.ShowDialog();
            //}));
        }

        private void InitVer() {
            this.Text = string.Format("{0} [Windstamp v.{1}]", this.Text, Application.ProductVersion);
        }

        private void InitZoomItems() {
            List<ZoomItem> zoomItems = new List<ZoomItem>() {
                new ZoomItem() { Name = "大", Number = 2 },
                new ZoomItem() { Name = "中", Number = 1 },
                new ZoomItem() { Name = "小", Number = 0 }
            };
            cmbZoom.ValueMember = "Number";
            cmbZoom.DisplayMember = "Name";
            cmbZoom.DataSource = zoomItems;
            cmbZoom.SelectedValue = 2;
        }

        private void InitData() {
            var data = DeserializeData<List<DownloadPageInfo>>();
            bData.Clear();
            ClearClipboard();
            if(data != null && data.Count > 0) {
                bData.DataSource = data;
            }
        }
        /// <summary>
        /// 序列化数据
        /// </summary>
        private void SerializeData<T>(T data) {
            Stream fStream = null;
            fStream = FileReset(fStream, Path.Combine(mainFolder, "bdata.wmd"));

            BinaryFormatter binFormat = new BinaryFormatter();
            binFormat.Serialize(fStream, data);
            fStream.Dispose();
            fStream.Close();
        }
        //重置文件
        private FileStream FileReset(Stream fStream, string fileName) {
            //关闭文件流
            if(fStream != null) {
                fStream.Close();
            }

            //删除文件
            File.Delete(fileName);

            //新建文件流
            return new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
        }
        /// <summary>
        /// 反序列化数据
        /// </summary>
        private T DeserializeData<T>() {
            T data = default(T);
            if(!File.Exists(Path.Combine(mainFolder, "bdata.wmd"))) {
                return data;
            }
            try {
                FileStream fStream = new FileStream(Path.Combine(mainFolder, "bdata.wmd"), FileMode.Open, FileAccess.Read);
                BinaryFormatter binFormat = new BinaryFormatter();
                data = (T)binFormat.Deserialize(fStream);
                fStream.Dispose();
                fStream.Close();
            } catch(Exception ex) {
                MessageBox.Show("数据读取错误：{0}", ex.Message);
            }
            return data;
        }

        void ClipboardMonitor() {
            Timer t = new Timer();
            t.Interval = 500;
            t.Tick += new EventHandler((object sender, EventArgs e) => {
                try {
                    this.Invoke(new Action(() => {
                        IDataObject d = Clipboard.GetDataObject();
                        if(!d.GetDataPresent(DataFormats.Text)) {
                            return;
                        }
                        string url = (string)d.GetData(DataFormats.Text);
                        if(!url.StartsWith("http://") || !url.Contains("/n/drspath_")) {
                            return;
                        }
                        if(((List<DownloadPageInfo>)bData.DataSource).Count(s => s.Url == url) > 0) {
                            return;
                        }

                        bData.Add(new DownloadPageInfo() {
                            Uid = Guid.NewGuid().ToString(),
                            Url = url,
                            BeginPage = 0,
                            EndPage = 0,
                            Status = DownloadPageStatus.Ready,
                            StatusName = downloadPageStatusNames[DownloadPageStatus.Ready],
                            Remove = "（×）移除"
                        });

                        SerializeData<List<DownloadPageInfo>>((List<DownloadPageInfo>)bData.DataSource);

                        PromptHelper.Handlers["StatusStripMsg"]("就绪", PromptType.Information);
                    }));
                } catch(Exception ex) {
                    PromptHelper.Handlers["StatusStripMsg"](string.Format("异常：{0}", ex.Message), PromptType.Error);
                }
            });
            t.Start();
        }

        void OnGridMainPageRemoveCellClick(object sender, DataGridViewCellEventArgs e) {
            if(gridMainPage.Columns[e.ColumnIndex].Name == "Remove") {
                if(((DownloadPageInfo)bData[e.RowIndex]).Status == DownloadPageStatus.Downloading) {
                    MessageBox.Show("当前行下载中，不能执行停止操作。");
                    return;
                }
                //((BindingSource)gridMainPage.DataSource).RemoveAt(e.RowIndex);
                // 要求列表的顺序跟数据的顺序是一样的
                bData.RemoveAt(e.RowIndex);
                SerializeData<List<DownloadPageInfo>>((List<DownloadPageInfo>)bData.DataSource);
                ClearClipboard();
            }
        }

        private void InitGridMainPage() {
            gridMainPage.AutoGenerateColumns = false;

            gridMainPage.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Url", DataPropertyName = "Url", HeaderText = "链接" });
            gridMainPage.Columns.Add(new DataGridViewTextBoxColumn() { Name = "BeginPage", DataPropertyName = "BeginPage", HeaderText = "起始页", ReadOnly = true });
            gridMainPage.Columns.Add(new DataGridViewTextBoxColumn() { Name = "EndPage", DataPropertyName = "EndPage", HeaderText = "结束页", ReadOnly = true });
            gridMainPage.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Status", DataPropertyName = "StatusName", HeaderText = "状态", ReadOnly = true });
            gridMainPage.Columns.Add(new DataGridViewLinkColumn() { Name = "Remove", DataPropertyName = "Remove", HeaderText = "移除", LinkColor = Color.Red, VisitedLinkColor = Color.Red, ActiveLinkColor = Color.Red, LinkBehavior = LinkBehavior.NeverUnderline });

            gridMainPage.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            gridMainPage.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            gridMainPage.Columns["Url"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;

            gridMainPage.Columns["BeginPage"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            gridMainPage.Columns["EndPage"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            gridMainPage.Columns["Status"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            gridMainPage.Columns["Remove"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;

            gridMainPage.Columns["BeginPage"].Width = 70;
            gridMainPage.Columns["EndPage"].Width = 70;
            gridMainPage.Columns["Status"].Width = 70;
            gridMainPage.Columns["Remove"].Width = 100;

            gridMainPage.MultiSelect = false;
        }

        private void InitPromptHelper() {
            PromptHelper.AddHandler(PromptPosition.Alert.ToString(), new Action<string, PromptType>((info, type) => {
                this.Invoke(new Action(() => {
                    string[] infoArr = info.Split('|');
                    string caption, msg;
                    if(infoArr.Length == 2) {
                        caption = infoArr[0].Trim();
                        msg = infoArr[1].Trim();
                    } else {
                        caption = "提示";
                        msg = info;
                    }
                    MessageBox.Show(this, msg, caption, MessageBoxButtons.OK, (MessageBoxIcon)type);
                }));
            }));

            PromptHelper.AddHandler(PromptPosition.StatusStripMsg.ToString(), new Action<string, PromptType>((info, type) => {
                this.Invoke(new Action(() => {
                    statusStrip1.Items[1].Text = info;
                    statusStrip1.Items[1].ForeColor = type == PromptType.Error ? Color.Red : Color.Black;
                }));
            }));

            PromptHelper.AddHandler(PromptPosition.StatusStripBookname.ToString(), new Action<string, PromptType>((info, type) => {
                this.Invoke(new Action(() => {
                    lblBookName.Text = info;
                    lblBookName.ForeColor = Color.Blue;
                }));
            }));
        }

        private void btnClear_Click(object sender, EventArgs e) {
            bData.Clear();

            string dataFile = Path.Combine(mainFolder, "bdata.wmd");
            if(File.Exists(dataFile)) {
                File.Delete(dataFile);
            }

            this.BeginInvoke(new Action(() => { ClearClipboard(); }));
        }
        private void ClearClipboard() {
            IDataObject d = Clipboard.GetDataObject();
            if(!d.GetDataPresent(DataFormats.Text)) {
                return;
            }
            string url = (string)d.GetData(DataFormats.Text);
            if(!url.StartsWith("http://") || !url.Contains("/n/drspath_")) {
                return;
            }
            Clipboard.Clear();
        }

        private void OnDownloadClick(object sender, EventArgs e) {
            int zoom;
            int.TryParse(cmbZoom.SelectedValue.ToString(), out zoom);
            ZoomHelper.Zoom = zoom;
            TimeHelper.Inteval = GetInteval();

            Button sendButton = (Button)sender;
            if(sendButton.Name == "btnAffiliatedPage") {
                statusStrip1.Items[1].Text = "开始下载附属页。";
            } else if(sendButton.Name == "btnMainPage") {
                statusStrip1.Items[1].Text = "开始下载正文页。";
            }

            if(bData != null && bData.Count == 0) {
                statusStrip1.Items[1].Text = "没有咨询信息。";
                return;
            }

            new BackgroundWorkerHelper().RunWorkerAsync(new Action<object, DoWorkEventArgs>((obj, args) => {
                var data = (List<DownloadPageInfo>)bData.DataSource;
                bool finishedOK = true;

                for(int i = 0; i < data.Count; i++) {
                    try {
                        DownloadEntrance entrance;
                        if(sendButton.Name == "btnAffiliatedPage") { // 附属页
                            currentEntrance = entrance = new DownloadEntrance();
                            entrance.AnalyzePage(data[0].Url);
                            PromptHelper.Handlers[PromptPosition.StatusStripBookname.ToString()](entrance.Info.Bookinfo, PromptType.Information);
                            entrance.StartAffiliatedDownload();
                        } else if(sendButton.Name == "btnMainPage") { // 正文页
                            if(data[i].Status == DownloadPageStatus.Finished) {
                                statusStrip1.Items[1].Text = string.Format("第 {0} 条（{1}页-{2}页）已下载过了，本次下载跳过。", i, data[i].BeginPage, data[i].EndPage);
                                continue;
                            }

                            gridMainPage.Invoke(new Action(() => { SetStatus(DownloadPageStatus.Downloading, data[i]); }));

                            currentEntrance = entrance = new DownloadEntrance();
                            entrance.AnalyzePage(data[i].Url);
                            PromptHelper.Handlers[PromptPosition.StatusStripBookname.ToString()](entrance.Info.Bookinfo, PromptType.Information);

                            gridMainPage.Invoke(new Action(() => {
                                DownloadPageInfo pageInfo = data[i];
                                pageInfo.BeginPage = entrance.Info.BeginPageNum;
                                gridMainPage.Rows[i].Cells["BeginPage"].Selected = true;
                                pageInfo.EndPage = entrance.Info.EndPageNum;
                                gridMainPage.Rows[i].Cells["EndPage"].Selected = true;
                                gridMainPage.Rows[i].Cells[0].Selected = true;
                            }));

                            entrance.StartDownloadMain();

                            gridMainPage.Invoke(new Action(() => { SetStatus(DownloadPageStatus.Finished, data[i]); }));
                        }
                    } catch(Exception ex) {
                        finishedOK = false;
                        if(ex.Message == "antispiderShowVerify") {
                            string url = gridMainPage.SelectedCells[0].Value.ToString();

                            this.Invoke(new Action(() => {
                                var webForm = new AntispiderShowVerifyForm() { AntispiderShowVerifyUrl = url };
                                webForm.Text = string.Format("{0}({1}-{2})", webForm.Text, data[i].BeginPage, data[i].EndPage);
                                webForm.ShowDialog();
                            }));

                            finishedOK = true;
                            i--;
                            continue;
                        } else if(ex.Message == "notGetUrl") {
                            statusStrip1.Items[1].Text = "未获取到重定向 Url";
                            gridMainPage.Invoke(new Action(() => { SetStatus(DownloadPageStatus.Error, data[i]); }));
                        } else if(ex.Message == "stopedByOther") {
                            statusStrip1.Items[1].Text = "已停止";
                            gridMainPage.Invoke(new Action(() => { SetStatus(DownloadPageStatus.Stoped, data[i]); }));
                            break;
                        } else if(ex.Message == "403") {
                            statusStrip1.Items[1].Text = "(403) 错误";
                            gridMainPage.Invoke(new Action(() => { SetStatus(DownloadPageStatus.Error, data[i]); }));
                            break;
                        } else {
                            MessageBox.Show(string.Format("异常：{0}", ex.Message));
                            gridMainPage.Invoke(new Action(() => { SetStatus(DownloadPageStatus.Error, data[i]); }));
                            break;
                        }
                    }
                }
                if(finishedOK) {
                    if(sendButton.Name == "btnAffiliatedPage") {
                        statusStrip1.Items[1].Text = "附属页下载完成。";
                    } else if(sendButton.Name == "btnMainPage") {
                        statusStrip1.Items[1].Text = "正文页下载完成。";
                    }
                }
                gridMainPage.BeginInvoke(new Action(() => { gridMainPage.Rows[0].Cells[0].Selected = true; }));
            }));
        }

        private void SetStatus(DownloadPageStatus status, DownloadPageInfo info) {
            switch(status) {
                case DownloadPageStatus.Ready:
                    info.Status = DownloadPageStatus.Ready;
                    info.StatusName = downloadPageStatusNames[DownloadPageStatus.Ready];
                    break;
                case DownloadPageStatus.Downloading:
                    info.Status = DownloadPageStatus.Downloading;
                    info.StatusName = downloadPageStatusNames[DownloadPageStatus.Downloading];
                    break;
                case DownloadPageStatus.Finished:
                    info.Status = DownloadPageStatus.Finished;
                    info.StatusName = downloadPageStatusNames[DownloadPageStatus.Finished];
                    break;
                case DownloadPageStatus.Stoped:
                    info.Status = DownloadPageStatus.Stoped;
                    info.StatusName = downloadPageStatusNames[DownloadPageStatus.Stoped];
                    break;
                case DownloadPageStatus.Error:
                    info.Status = DownloadPageStatus.Error;
                    info.StatusName = downloadPageStatusNames[DownloadPageStatus.Error];
                    break;
            }
            gridMainPage.Rows[bData.IndexOf(info)].Cells[0].Selected = true;
            gridMainPage.Rows[bData.IndexOf(info)].Cells["Status"].Value = info.StatusName;
        }

        private void btnRestore_Click(object sender, EventArgs e) {
            InitData();
        }

        private void btnPause_Click(object sender, EventArgs e) {
            currentEntrance.Stop();
        }

        private void btnOpenDir_Click(object sender, EventArgs e) {
            string rootFolder = @"D:\ysm\";
            if(!Directory.Exists(rootFolder)) {
                Directory.CreateDirectory(rootFolder);
            }
            System.Diagnostics.Process.Start(rootFolder);
        }

        private void OnOpenThirdPartyTool(object sender, EventArgs e) {
            string fileFullName = "";
            switch(((Control)sender).Name) {
                case "btnPDFBuilder": // 打开 “PDF制作” 工具
                    fileFullName = Path.Combine(mainFolder, @"FreePic2PDF\pdf.exe");
                    break;
                case "btnPDFEditor": // 打开 “PDF编辑” 工具
                    fileFullName = Path.Combine(mainFolder, @"FoxitPDFEditor\PDFEdit.exe");
                    break;
                case "btnPDFPatcher": // 打开 “PDF补丁丁” 工具
                    fileFullName = Path.Combine(mainFolder, @"PDFPatcher\PDFPatcher.exe");
                    break;
            }
            try {
                ProcessStartInfo info = new ProcessStartInfo(fileFullName);
                System.Diagnostics.Process.Start(info);
            } catch(Exception ex) {
                PromptHelper.Handlers[PromptPosition.Alert.ToString()](ex.Message, PromptType.Error);
            }
        }

        /// <summary>
        /// 获取延时时间（单位：毫秒）
        /// </summary>
        /// <returns></returns>
        private int GetInteval() {
            string intevalStr = string.IsNullOrEmpty(txtInteval.Text) ? "0" : txtInteval.Text;
            int result;
            int.TryParse(intevalStr, out result);
            return result * 1000;
        }

        private void txtInteval_MouseUp(object sender, MouseEventArgs e) {
            base.OnMouseUp(e);

            if(e.Button == MouseButtons.Right) {
                menuInteval.Show((Control)sender, e.Location);
            }
        }

        private void menuInteval_ItemClicked(object sender, ToolStripItemClickedEventArgs e) {
            txtInteval.Text = e.ClickedItem.Text;
        }

        private void txtInteval_DoubleClick(object sender, EventArgs e) {
            txtInteval.Text = "0";
        }
    }

    [Serializable]
    class DownloadPageInfo {
        /// <summary>
        /// Uid
        /// </summary>
        public string Uid { get; set; }

        /// <summary>
        /// 链接
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// 起始页
        /// </summary>
        public int BeginPage { get; set; }

        /// <summary>
        /// 结束页
        /// </summary>
        public int EndPage { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public DownloadPageStatus Status { get; set; }

        /// <summary>
        /// 状态名
        /// </summary>
        public string StatusName { get; set; }

        /// <summary>
        /// 移除
        /// </summary>
        public string Remove { get; set; }

        /// <summary>
        /// 是否可用
        /// </summary>
        public bool Usable { get; set; }
    }

    /// <summary>
    /// 下载页状态
    /// </summary>
    enum DownloadPageStatus {
        Ready = 0,
        Downloading = 1,
        Finished = 2,
        Stoped = 3,
        Error = 4
    }

    /// <summary>
    /// zoom 项
    /// </summary>
    class ZoomItem {
        /// <summary>
        /// zoom 号
        /// </summary>
        public int Number { get; set; }

        /// <summary>
        /// zoom 名
        /// </summary>
        public string Name { get; set; }
    }
}
